﻿#region Header
// ------------------------ Licence / Copyright ------------------------
// 
// ScrumTable for Scrum Meeting Support
// Copyright © HSR - Hochschule für Technik Rapperswil
// All Rights Reserved
// 
// Author:
//  Michael Gfeller Silvan Gehrig Patrick Boos
// 
// ---------------------------------------------------------------------
#endregion

#region Usings

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using ScrumTable.Common.Collections;
using ScrumTable.Common.Test;
using ScrumTable.DL.Data.Generic.Cache;

using WorkItemBucket = ScrumTable.DL.Data.Generic.Cache.CacheElementListEntryBucket<ScrumTable.DL.Data.Generic.Cache.CacheWorkItem>;
using WorkItemSavePair = ScrumTable.DL.Data.Generic.Cache.CacheSavePair<ScrumTable.DL.Data.Generic.Cache.CacheElementListEntryBucket<ScrumTable.DL.Data.Generic.Cache.CacheWorkItem>>;

#endregion


namespace ScrumTable.DL.Data.Generic.Test.Cache
{
    /// <summary>
    /// This is the test class for CacheWorkItemLink class.
    /// </summary>
    [TestClass]
    public class CacheWorkItemLinkTest : CacheElementBaseTest<CacheWorkItemLink>
    {
        #region Declarations
        //--------------------------------------------------------------------
        // Declarations
        //--------------------------------------------------------------------

        #endregion

        #region Properties
        //--------------------------------------------------------------------
        // Properties
        //--------------------------------------------------------------------

        private CacheProject Project { get; set; }
        private CacheWorkItem UserStory { get; set; }

        #endregion

        #region Additional test attributes
        //
        // You can use the following additional attributes as you write your tests:
        //
        // Use ClassInitialize to run code before running the first test in the class
        // [ClassInitialize()]
        // public static void MyClassInitialize(TestContext testContext) { }
        //
        // Use ClassCleanup to run code after all tests in a class have run
        // [ClassCleanup()]
        // public static void MyClassCleanup() { }
        //
        // Use TestInitialize to run code before running each test 
        // [TestInitialize()]
        // public void MyTestInitialize() { }
        //
        // Use TestCleanup to run code after each test has run
        // [TestCleanup()]
        // public void MyTestCleanup() { }
        //
        #endregion

        #region Constructors / Destructor
        //--------------------------------------------------------------------
        // Constructors / Destructor
        //--------------------------------------------------------------------

        /// <summary>
        /// Creates a new CacheWorkItemLinkTest instance.
        /// </summary>
        public CacheWorkItemLinkTest()
        {
        }

        #endregion

        #region Methods
        //--------------------------------------------------------------------
        // Methods
        //--------------------------------------------------------------------

        /// <summary>
        /// Use TestInitialize to run code before running each test .
        /// </summary>
        [TestInitialize]
        public override void TestInitialize()
        {
            base.TestInitialize();

            Project = CacheContext.Projects.TryGetById(Resources.Project1.Id);
            UserStory = Project.WorkItems.TryGetById(ResourceManager.UserStory2Id);
            ToTest = UserStory.ChildLinks.First();
        }

        /// <summary>
        /// Use TestCleanup to run code after each test has run.
        /// </summary>
        [TestCleanup]
        public override void TestCleanup()
        {
            ToTest = null;
            base.TestCleanup();
        }

        [TestMethod]
        public void TestNewChildTaskFromServer()
        {
            int oldWiLinkCount = UserStory.ChildLinks.Count();

            CacheWorkItemLink newLink = CacheContext.ElementFactory.CreateWorkItemLink(UserStory.Id);
            ValueChain<string> newChildChain = new ValueChain<string>(Resources.Project1.UniqueId, UserStory.UniqueId);

            // special case: in mean time there's a new workitem on server side
            CacheWorkItem newSeverTask = CacheContext.ElementFactory.CreateWorkItem(
                Project.TaskType, 101, "WorkItem 101",
                1, CacheIdentity.DefaultId, Project.TaskType.Workflow.TransitionStart,
                string.Empty, Resources.Member1.DisplayName,
                new Dictionary<string, object>(), new[] { newLink }, new CacheWorkItemLink[0], new CacheAttachment[0],
                new CacheWorkItemRevision[0]);

            // emulate data driver: accept the changes (a new workitem on server side is available)
            CacheDataChanges changes = DataContext.ExportChanges();
            WorkItemBucket newBucket = new WorkItemBucket { Element = newSeverTask };
            changes.WorkItemsToSync[newSeverTask.UniqueId] = new WorkItemSavePair(newBucket)
            {
                State = CacheSavePairState.Updated
            };

            changes.RemoveDirtyFlags();
            DataContext.ImportChanges(changes);

            // this link must be generated dynamically by the data layer
            //  -> TFS does not create a work item link from parent to child neither
            CacheWorkItemLink newLinkToTask = CacheContext.ElementFactory.CreateWorkItemLink(newSeverTask.Id, newSeverTask.UniqueId);

            // make sure child link is available
            Assert.AreEqual(oldWiLinkCount + 1, UserStory.ChildLinks.Count());
            Assert.IsTrue(newSeverTask.ParentLinks.Contains(newLink));
            Assert.IsTrue(UserStory.ChildLinks.Contains(newLinkToTask));
            
            // make sure parent link is available
            CacheWorkItem retrievedWi = Project.WorkItems.TryGetChild(newChildChain, newSeverTask.UniqueId);
            Assert.IsNotNull(retrievedWi);
            Assert.AreEqual(1, retrievedWi.ParentLinks.Count);
            Assert.AreEqual(newSeverTask.UniqueId, retrievedWi.UniqueId);
        }

        [TestMethod]
        public void TestNewChildLinkFromServer()
        {
            CacheWorkItem newParentToModify = (CacheWorkItem)Project.WorkItems.TryGetById(ResourceManager.UserStory1Id).Clone();
            CacheWorkItem oldParentToModify = (CacheWorkItem)Project.WorkItems.TryGetById(ResourceManager.UserStory2Id).Clone();
            CacheWorkItem childToMove = (CacheWorkItem)Project.WorkItems.TryGetById(ResourceManager.Task1Id).Clone();

            CacheDataChanges changes = DataContext.ExportChanges();
            CacheWorkItemLink linkToChild = changes.Project.OwnerContext.ElementFactory.CreateWorkItemLink(childToMove.Id, childToMove.UniqueId);
            CacheWorkItemLink oldParentLink = changes.Project.OwnerContext.ElementFactory.CreateWorkItemLink(oldParentToModify.Id, oldParentToModify.UniqueId);
            CacheWorkItemLink newParentLink = changes.Project.OwnerContext.ElementFactory.CreateWorkItemLink(newParentToModify.Id, newParentToModify.UniqueId);

            oldParentToModify.ChildLinks.Remove(linkToChild);
            childToMove.ParentLinks.Remove(oldParentLink);

            newParentToModify.ChildLinks.Add(linkToChild);
            childToMove.ParentLinks.Add(newParentLink);

            WorkItemBucket newParent1Bucket = new WorkItemBucket { Element = newParentToModify };
            WorkItemBucket newParent2Bucket = new WorkItemBucket { Element = oldParentToModify };
            WorkItemBucket newChild1Bucket = new WorkItemBucket { Element = childToMove };
            changes.WorkItemsToSync[newParentToModify.UniqueId] = new WorkItemSavePair(newParent1Bucket) { State = CacheSavePairState.Updated };
            changes.WorkItemsToSync[oldParentToModify.UniqueId] = new WorkItemSavePair(newParent2Bucket) { State = CacheSavePairState.Updated };
            changes.WorkItemsToSync[childToMove.UniqueId] = new WorkItemSavePair(newChild1Bucket) { State = CacheSavePairState.Updated };
            changes.RemoveDirtyFlags();

            DataContext.ImportChanges(changes);

            Assert.IsNotNull(Project.WorkItems.TryGetChild(new ValueChain<string>(Project.UniqueId, newParentToModify.UniqueId), childToMove.UniqueId));
            Assert.IsNull(Project.WorkItems.TryGetChild(new ValueChain<string>(Project.UniqueId, oldParentToModify.UniqueId), childToMove.UniqueId));
        }

        [TestMethod]
        public void TestNewChildLinkFromServerWithInconsistency()
        {
            CacheWorkItem newParentToModify = (CacheWorkItem)Project.WorkItems.TryGetById(ResourceManager.UserStory1Id).Clone();
            CacheWorkItem oldParentToModify = (CacheWorkItem)Project.WorkItems.TryGetById(ResourceManager.UserStory2Id).Clone();
            CacheWorkItem childToMove = (CacheWorkItem)Project.WorkItems.TryGetById(ResourceManager.Task1Id).Clone();

            CacheDataChanges changes = DataContext.ExportChanges();

            childToMove.ParentLinks.Remove(changes.Project.OwnerContext.ElementFactory.CreateWorkItemLink(oldParentToModify.Id, oldParentToModify.UniqueId));
            childToMove.ParentLinks.Add(changes.Project.OwnerContext.ElementFactory.CreateWorkItemLink(newParentToModify.Id, newParentToModify.UniqueId));

            WorkItemBucket newChild1Bucket = new WorkItemBucket { Element = childToMove };
            changes.WorkItemsToSync[childToMove.UniqueId] = new WorkItemSavePair(newChild1Bucket) { State = CacheSavePairState.Updated };
            changes.RemoveDirtyFlags();

            DataContext.ImportChanges(changes);

            Assert.IsNotNull(Project.WorkItems.TryGetChild(new ValueChain<string>(Project.UniqueId, newParentToModify.UniqueId), childToMove.UniqueId));
            Assert.IsNull(Project.WorkItems.TryGetChild(new ValueChain<string>(Project.UniqueId, oldParentToModify.UniqueId), childToMove.UniqueId));
        }

        [TestMethod]
        public void TestRemoveChildLinkFromServer()
        {
            CacheDataChanges changes = DataContext.ExportChanges();

            // test if a child already exists
            CacheWorkItem parentStoryClone = (CacheWorkItem)Project.WorkItems.TryGetById(ResourceManager.UserStory2Id).Clone();
            CacheWorkItem childTask = Project.WorkItems.TryGetById(ResourceManager.Task1Id);

            // check if the child task is imported on the right level
            Assert.IsNotNull(Project.WorkItems.TryGetChild(new ValueChain<string>(Project.UniqueId, parentStoryClone.UniqueId), childTask.UniqueId));

            // remove link from clone to merge it with the cache
            parentStoryClone.ChildLinks.Remove(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(childTask.Id, childTask.UniqueId));

            WorkItemBucket parentStoryCloneBucket = new WorkItemBucket { Element = parentStoryClone };
            changes.WorkItemsToSync[parentStoryClone.UniqueId] = new WorkItemSavePair(parentStoryCloneBucket) { State = CacheSavePairState.Updated };
            changes.RemoveDirtyFlags();

            DataContext.ImportChanges(changes);

            Assert.IsNotNull(Project.WorkItems.TryGetChild(new ValueChain<string>(Project.UniqueId), parentStoryClone.UniqueId));
            Assert.IsNull(Project.WorkItems.TryGetChild(new ValueChain<string>(Project.UniqueId, parentStoryClone.UniqueId), childTask.UniqueId));
        }

        [TestMethod]
        [ExpectedException(typeof(InvalidOperationException))]
        public void TestGetChangesRelationsExists()
        {
            // test if a child already exists
            CacheWorkItem parentStory = Project.WorkItems.TryGetById(ResourceManager.UserStory2Id);
            CacheWorkItem childTask = Project.WorkItems.TryGetById(ResourceManager.Task1Id);

            // this step must throw the InvalidOperationException
            parentStory.ChildLinks.Add(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(childTask.Id, childTask.UniqueId));
        }

        [TestMethod]
        public void TestGetChangesRelationsRecreate()
        {
            // test if a has been deleted and recreated, this should result in an empty change set
            CacheWorkItem parentStory = Project.WorkItems.TryGetById(ResourceManager.UserStory2Id);
            CacheWorkItem childTask = Project.WorkItems.TryGetById(ResourceManager.Task1Id);

            parentStory.ChildLinks.Remove(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(childTask.Id, childTask.UniqueId));
            Assert.IsTrue(parentStory.IsDirty);

            parentStory.ChildLinks.Add(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(childTask.Id, childTask.UniqueId));
            Assert.IsFalse(parentStory.IsDirty);
            Assert.AreEqual(0, DataContext.ExportChanges().ChangedWorkItems.Count);
        }

        [TestMethod]
        public void TestGetChangesRelationsCreate()
        {
            CacheWorkItem parentStory = Project.WorkItems.TryGetById(ResourceManager.UserStory2Id);
            CacheWorkItem childTask = Project.WorkItems.TryGetById(ResourceManager.Task1Id);

            // remove child link (init test)
            Assert.IsTrue(childTask.ParentLinks.Contains(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(parentStory.Id, parentStory.UniqueId)));
            parentStory.ChildLinks.Remove(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(childTask.Id, childTask.UniqueId));
            Assert.IsNull(childTask.ParentLink);
            Assert.IsTrue(childTask.IsDirty);
            Assert.IsTrue(parentStory.IsDirty);

            // remove dirty flags & states
            parentStory.RemoveDirtyFlag();
            childTask.RemoveDirtyFlag();

            // add new link to test relation create
            childTask.ParentLinks.Add(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(parentStory.Id, parentStory.UniqueId));

            // test if parent and child links are available
            Assert.IsTrue(parentStory.IsDirty);
            Assert.IsTrue(childTask.IsDirty);
            Assert.IsNotNull(childTask.ParentLink);
            Assert.IsTrue(childTask.ParentLinks.Contains(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(parentStory.Id, parentStory.UniqueId)));
            Assert.IsTrue(parentStory.ChildLinks.Contains(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(childTask.Id, childTask.UniqueId)));
            Assert.AreEqual(parentStory.UniqueId, childTask.ParentLink.RelatedUnqiueId);
            Assert.AreEqual(parentStory.Id, childTask.ParentLink.RelatedId);
        }

        [TestMethod]
        public void TestGetChangesRelations()
        {
            // test normal change set / export changes behaviour
            CacheWorkItem parentStory = Project.WorkItems.TryGetById(ResourceManager.UserStory1Id);
            CacheWorkItem childTask = Project.WorkItems.TryGetById(ResourceManager.Task1Id);
            CacheWorkItem oldParentStory = Project.WorkItems.TryGetById(childTask.ParentLink.RelatedId);

            childTask.ParentLinks.Add(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(parentStory.Id, parentStory.UniqueId));
            TestGetChangesRelationsExportCheck(3, childTask, parentStory, oldParentStory);

            childTask.ParentLinks.Remove(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(parentStory.Id, parentStory.UniqueId));
            TestGetChangesRelationsExportCheck(2, childTask, parentStory);
        }

        private CacheDataChanges TestGetChangesRelationsExportCheck(int numberOfChanges, CacheWorkItem childTask, CacheWorkItem parentStory, CacheWorkItem oldParentStory = null)
        {
            Assert.IsTrue(parentStory.IsDirty);
            Assert.IsTrue(childTask.IsDirty);
            if (oldParentStory != null) { Assert.IsTrue(oldParentStory.IsDirty); }

            CacheDataChanges changes = DataContext.ExportChanges();
            Assert.IsFalse(parentStory.IsDirty);
            Assert.IsFalse(childTask.IsDirty);
            if (oldParentStory != null) { Assert.IsFalse(oldParentStory.IsDirty); }

            Assert.AreEqual(numberOfChanges, changes.ChangedWorkItems.Count);
            Assert.AreEqual(0, changes.ChangedIterations.Count);
            
            Assert.IsNotNull(changes.ChangedWorkItems.Where(x => x.Value.Element.UniqueId == childTask.UniqueId).FirstOrDefault());
            Assert.IsNotNull(changes.ChangedWorkItems.Where(x => x.Value.Element.UniqueId == parentStory.UniqueId).FirstOrDefault());
            if (oldParentStory != null) { Assert.IsNotNull(changes.ChangedWorkItems.Where(x => x.Value.Element.UniqueId == oldParentStory.UniqueId).FirstOrDefault()); }

            changes.ChangedWorkItems.ForEach(wiBucket => Assert.IsFalse(wiBucket.Value.Element.IsContextConnected));
            return changes;
        }

        
        [TestMethod]
        public void TestSwapElementsFromServer()
        {
            CacheWorkItem parentStory2 = Project.WorkItems.TryGetById(ResourceManager.UserStory2Id);
            CacheWorkItem parentStory3 = Project.WorkItems.TryGetById(ResourceManager.UserStory3Id);

            // simulate data driver
            CacheWorkItem parentStoryClone2 = (CacheWorkItem)parentStory2.Clone();
            CacheWorkItem parentStoryClone3 = (CacheWorkItem)parentStory3.Clone();

            CacheWorkItemLink parentLinkToTask1 = ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(Resources.Task1.Id, Resources.Task1.UniqueId);
            CacheWorkItemLink parentLinkToTask2 = ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(Resources.Task2.Id, Resources.Task2.UniqueId);

            // swap child link instances from parentStory2 to parentStory3
            parentStoryClone2.ChildLinks.Remove(parentLinkToTask1);
            parentStoryClone3.ChildLinks.Add(parentLinkToTask1);

            parentStoryClone3.ChildLinks.Remove(parentLinkToTask2);
            parentStoryClone2.ChildLinks.Add(parentLinkToTask2);

            // fill in the changes into the data driver
            CacheDataChanges changes = DataContext.ExportChanges();
            WorkItemBucket bucketStory2 = new WorkItemBucket { Element = parentStoryClone2 };
            WorkItemBucket bucketStory3 = new WorkItemBucket { Element = parentStoryClone3 };

            changes.WorkItemsToSync[parentStoryClone2.UniqueId] = new CacheSavePair<CacheElementListEntryBucket<CacheWorkItem>>(bucketStory2) { State = CacheSavePairState.Updated };
            changes.WorkItemsToSync[parentStoryClone3.UniqueId] = new CacheSavePair<CacheElementListEntryBucket<CacheWorkItem>>(bucketStory3) { State = CacheSavePairState.Updated };
            changes.RemoveDirtyFlags();

            // update elements and watch for changes
            DataContext.ImportChanges(changes);

            // make sure the data import does not cause internal changes
            Assert.IsFalse(parentStory2.IsDirty);
            Assert.IsFalse(parentStory3.IsDirty);
            Assert.IsTrue(DataContext.ExportChanges().ChangedWorkItems.Count == 0);
        }

        [TestMethod]
        public void TestGetChangesRelationsWithReject()
        {
            // test normal change set / export changes behaviour
            CacheWorkItem newParentStory = Project.WorkItems.TryGetById(ResourceManager.UserStory1Id);
            CacheWorkItem childTask = Project.WorkItems.TryGetById(ResourceManager.Task1Id);
            CacheWorkItem parentStory = Project.WorkItems.TryGetById(childTask.ParentLink.RelatedId);

            childTask.ParentLinks.Add(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(newParentStory.Id, newParentStory.UniqueId));

            // nothing happens on data layer level (except some checks)
            CacheDataChanges changes = TestGetChangesRelationsExportCheck(3, childTask, newParentStory, parentStory);

            // lets import the exported elements again. this must result in a reject of all elements
            DataContext.ImportChanges(changes);

            Assert.IsTrue(newParentStory.IsDirty);
            Assert.IsTrue(childTask.IsDirty);
            Assert.IsTrue(parentStory.IsDirty);

            // the export state must be same as before the first export
            TestGetChangesRelationsExportCheck(3, childTask, newParentStory);
        }

        [TestMethod]
        public void TestGetChangesRelationsWithMultipleReject()
        {
            // test normal change set / export changes behaviour
            CacheWorkItem newParentStory = Project.WorkItems.TryGetById(ResourceManager.UserStory1Id);
            CacheWorkItem newParentStoryDuringExport = Project.WorkItems.TryGetById(ResourceManager.UserStory3Id);
            CacheWorkItem childTask = Project.WorkItems.TryGetById(ResourceManager.Task1Id);
            CacheWorkItem parentStory = Project.WorkItems.TryGetById(childTask.ParentLink.RelatedId);

            childTask.ParentLinks.Add(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(newParentStory.Id, newParentStory.UniqueId));

            // nothing happens on data layer level (except some checks)
            CacheDataChanges changes = TestGetChangesRelationsExportCheck(3, childTask, newParentStory, parentStory);

            childTask.ParentLinks.Add(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(newParentStoryDuringExport.Id, newParentStoryDuringExport.UniqueId));

            Assert.IsTrue(newParentStory.IsDirty);
            Assert.IsTrue(newParentStoryDuringExport.IsDirty);
            Assert.IsTrue(childTask.IsDirty);
            Assert.IsFalse(parentStory.IsDirty);

            // lets import the exported elements again. this must result in a reject of all elements
            DataContext.ImportChanges(changes);

            // all changes are incremented
            Assert.IsTrue(newParentStory.IsDirty);
            Assert.IsTrue(newParentStoryDuringExport.IsDirty);
            Assert.IsTrue(childTask.IsDirty);
            Assert.IsTrue(parentStory.IsDirty);

            TestGetChangesRelationsExportCheck(4, childTask, newParentStoryDuringExport, newParentStory);
        }

        [TestMethod]
        public void TestGetChangesIsSyncEventsOfRelationsWithReject()
        {
            // test normal change set / export changes behaviour
            CacheWorkItem newParentStory = Project.WorkItems.TryGetById(ResourceManager.UserStory1Id);
            CacheWorkItem childTask = Project.WorkItems.TryGetById(ResourceManager.Task1Id);
            CacheWorkItem parentStory = Project.WorkItems.TryGetById(childTask.ParentLink.RelatedId);

            childTask.ParentLinks.Add(ToTest.OwnerContext.ElementFactory.CreateWorkItemLink(newParentStory.Id, newParentStory.UniqueId));

            // make sure elements are dirty but not synchronized
            Assert.IsTrue(newParentStory.IsDirty);
            Assert.IsTrue(childTask.IsDirty);
            Assert.IsTrue(parentStory.IsDirty);
            Assert.IsFalse(childTask.IsSynchronized);
            Assert.IsFalse(newParentStory.IsSynchronized);
            Assert.IsFalse(parentStory.IsSynchronized);

            // nothing happens on data layer level (except some checks)
            CacheDataChanges changes = DataContext.ExportChanges();
            changes.MarkChangesAs(CacheSavePairState.Saved);

            NotifyPropertyTestStub<CacheWorkItem, bool> newParentStoryTester = new NotifyPropertyTestStub<CacheWorkItem, bool>(
                newParentStory,
                () => newParentStory.IsSynchronized) { PropertyName = "IsSynchronized" };
            NotifyPropertyTestStub<CacheWorkItem, bool> childTaskTester = new NotifyPropertyTestStub<CacheWorkItem, bool>(
                childTask,
                () => childTask.IsSynchronized) { PropertyName = "IsSynchronized" };
            NotifyPropertyTestStub<CacheWorkItem, bool> parentStoryTester = new NotifyPropertyTestStub<CacheWorkItem, bool>(
                parentStory,
                () => parentStory.IsSynchronized) { PropertyName = "IsSynchronized" };

            using (newParentStoryTester.Register())
            {
                using (childTaskTester.Register())
                {
                    using (parentStoryTester.Register())
                    {
                        // lets import the exported elements again. this must result in a reject of all elements
                        DataContext.ImportChanges(changes);
                    }
                }
            }

            // after import, elements mustn't be dirty anymore
            Assert.IsFalse(newParentStory.IsDirty);
            Assert.IsFalse(childTask.IsDirty);
            Assert.IsFalse(parentStory.IsDirty);

            // after import, elements must be synchronized
            Assert.IsTrue(newParentStory.IsSynchronized);
            Assert.IsTrue(childTask.IsSynchronized);
            Assert.IsTrue(parentStory.IsSynchronized);

            // make sure IsSynchronized events are fired
            Assert.AreEqual(1, childTaskTester.PropertyFiredCount);
            Assert.AreEqual(1, childTaskTester.PropertyFiringCount);
            Assert.AreEqual(1, newParentStoryTester.PropertyFiredCount);
            Assert.AreEqual(1, newParentStoryTester.PropertyFiringCount);
            Assert.AreEqual(1, parentStoryTester.PropertyFiredCount);
            Assert.AreEqual(1, parentStoryTester.PropertyFiringCount);
        }

        #endregion

        #region Events
        //--------------------------------------------------------------------
        // Events
        //--------------------------------------------------------------------

        #endregion
    }
}
